package drds.plus.rule_engine.rule;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 通过表达式来表达规则的基类
 */
public abstract class ExpressionRule<T> implements Rule<T> {

    private static final Pattern DOLLER_PATTERN = Pattern.compile("\"#.*?#\"");

    /**
     * 当前规则需要用到的参数
     */
    protected final Map<String/* 小写列名 */, RuleColumn> columnToRuleColumnMap;
    protected final Set<RuleColumn> ruleColumnSet; // 规则列
    protected final String originExpression; // 原始的表达式
    /**
     * 当前规则需要用到的表达式
     */
    protected String expression;

    public ExpressionRule(String expression) {
        this.originExpression = expression;
        this.expression = expression;
        this.columnToRuleColumnMap = Collections.unmodifiableMap(parse());
        this.ruleColumnSet = new HashSet<RuleColumn>(columnToRuleColumnMap.size());
        this.ruleColumnSet.addAll(columnToRuleColumnMap.values());
    }

    private Map<String, RuleColumn> parse() {
        Map<String, RuleColumn> columnToRuleColumnMap = new HashMap<String, RuleColumn>();
        Matcher matcher = DOLLER_PATTERN.matcher(expression);
        int start = 0;
        StringBuffer sb = new StringBuffer();
        while (matcher.find(start)) {
            String realParam = matcher.group();
            realParam = realParam.substring(1, realParam.length() - 1);
            sb.append(expression, start, matcher.start());
            sb.append(parseParam(realParam, columnToRuleColumnMap));
            start = matcher.end();
        }
        sb.append(expression.substring(start));
        expression = sb.toString();
        return columnToRuleColumnMap;
    }

    /**
     * 子类将paramInDoller解析为RuleColumn，加入到parameters中，并返回替换后的字串
     *
     * @param paramInDoller
     * @param parameters
     * @return 替换后的字串
     */
    abstract protected String parseParam(String paramInDoller, Map<String, RuleColumn> parameters);

    public Map<String, RuleColumn> getColumnNameToRuleColumnMap() {
        return columnToRuleColumnMap;
    }

    public Set<RuleColumn> getRuleColumnSet() {
        return ruleColumnSet;
    }

    public String getExpression() {
        return originExpression;
    }

    /**
     * originExpression相同则相同，eclipse生成
     */
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        ExpressionRule other = (ExpressionRule) obj;
        if (originExpression == null) {
            return other.originExpression == null;
        } else return originExpression.equals(other.originExpression);
    }

    /**
     * eclipse生成
     */
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((originExpression == null) ? 0 : originExpression.hashCode());
        return result;
    }
}
